﻿/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Reflection;
using Metalama.Framework.Aspects;
using Metalama.Framework.Code;
using Metalama.Framework.Eligibility;
using Servicecomb.Saga.Omega.Abstractions.Context;
using Servicecomb.Saga.Omega.Abstractions.Logging;
using ServiceLocator = Servicecomb.Saga.Omega.Abstractions.Transaction.Extensions.ServiceLocator;

namespace Servicecomb.Saga.Omega.Abstractions.Transaction
{
    // Metalama 方面（Aspect）替代原有的特性
    [AttributeUsage(AttributeTargets.Method)]
    public class SagaStartAttribute : OverrideMethodAspect
    {
        [Introduce(WhenExists = OverrideStrategy.Ignore)]
        public static ILogger _logger = LogManager.GetLogger(typeof(SagaStartAttribute));

        [Introduce(WhenExists = OverrideStrategy.Ignore)]
        public static ISagaStartEventAwareInterceptor _sagaStartAnnotationProcessor;

        [Introduce(WhenExists = OverrideStrategy.Ignore)]
        public static OmegaContext _omegaContext;

        public int TimeOut { get; set; } = 0;

        // 构建时初始化静态依赖
        static SagaStartAttribute()
        {
            // 注意：在编译时无法解析服务，所以这里使用延迟初始化
            // 实际服务解析将在运行时进行
        }

        // 重写此方法以定义要织入的代码
        public override dynamic? OverrideMethod()
        {
            // 运行时初始化依赖（如果尚未初始化）
            if (_omegaContext == null)
            {
                _omegaContext = (OmegaContext)ServiceLocator.Current.GetInstance(typeof(OmegaContext));
                _sagaStartAnnotationProcessor = (ISagaStartEventAwareInterceptor)ServiceLocator.Current.GetInstance(typeof(ISagaStartEventAwareInterceptor));
            }

            // 相当于原来的 OnEntry
            //InitializeOmegaContext();

            // 初始化 OmegaContext
            _omegaContext.SetLocalTxId(_omegaContext.NewGlobalTxId());

            _sagaStartAnnotationProcessor.PreIntercept(_omegaContext.GetGlobalTxId(), meta.Target.Method.Name, TimeOut, "", 0);
            _logger.Debug($"Initialized context {_omegaContext} before execution of method {meta.Target.Method.Name}");

            try
            {
                // 执行原始方法
                var result = meta.Proceed();

                // 相当于原来的 OnExit
                _sagaStartAnnotationProcessor.PostIntercept(_omegaContext.GetGlobalTxId(), meta.Target.Method.Name);
                _logger.Debug($"Transaction with context {_omegaContext} has finished.");

                return result;
            }
            catch (Exception e)
            {
                // 相当于原来的 OnException
                _sagaStartAnnotationProcessor.OnError(null, "", e);
                _logger.Error($"Transaction {_omegaContext.GetGlobalTxId()} failed.", e);
                throw;
            }
        }

        // 这个方法只在运行时调用，所以不需要特殊处理
        /*private void InitializeOmegaContext(IOmegaContext omegaContext)
        {
            omegaContext.SetLocalTxId(omegaContext.NewGlobalTxId());
        }*/

        // 可选：定义方面应用于哪些方法
        public override void BuildEligibility(IEligibilityBuilder<IMethod> builder)
        {
            base.BuildEligibility(builder);
            // 可以添加 eligibility 规则
        }
    }
}
